<!DOCTYPE html>
<html lang="zh-CN">

<!-- Head tag -->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  
  <meta name="baidu-site-verification" content="undefined" />
  <meta name="google-site-verification" content="undefined" />
  <meta name="msvalidate.01" content="undefined" />
  <meta name="360-site-verification" content="undefined" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- if page has tags, then add tags to keyword -->
  
  
  <meta name="keywords" content=",Golang汇编,Golang底层,Golang,">
  <!-- page.description has higher priority -->
  <meta name="description" content="看看常见的数据结构在汇编代码中的展现">
  <link rel="shortcut icon" href="/blog/img/logo.webp">
  <title>
    
    Golang汇编(四)-汇编眼中的数据结构 | Evrn
    
  </title>

  <link rel="canonical" href="/blog/post/go-asm-datastruct.html">
  
<link rel="stylesheet" href="/blog/css/reset.css">

  
<link rel="stylesheet" href="/blog/css/layout.css">

  
<link rel="stylesheet" href="/blog/css/markdown.css">

  <!-- Pygments Highlight CSS -->
  
<link rel="stylesheet" href="/blog/css/highlight.css">

  
<link rel="stylesheet" href="/blog/css/geektutu.css">

  <!-- global function -->
  <script>
    window.globalAddScript = function (url, onload, onerror) {
      var s = document.createElement('script');
      s.src = url;
      onload && (s.onload = onload);
      onerror && (s.onerror = onerror);
      document.body.appendChild(s);
    }
    window.globalAddCss = function (url) {
      var s = document.createElement('link');
      s.rel = 'stylesheet';
      s.href = url;
      document.body.appendChild(s);
    }
    window.getPosition = function (ele) {
      var x = 0, y = 0;
      while (ele) {
        x += (ele.offsetLeft - ele.scrollLeft + ele.clientLeft);
        y += (ele.offsetTop - ele.scrollTop + ele.clientTop);
        ele = ele.offsetParent;
      }
      return { x: x, y: y };
    }
    window.getDom = function (str) { return document.querySelector(str) }
  </script>
  <!-- google ad -->
  
<meta name="generator" content="Hexo 4.2.0"></head>

<body>
    <header class="gkt-header col-xs-12 padding-0">
    <div id="gkt-nav" class="gkt-header-container">
        <a href="/blog/" class="gkt-header-title float-left">
            <img class="float-left" src="/blog/img/logo.webp" alt="">
            <span>Evrn</span>
        </a>
        <nav class="gkt-header-nav text-right">
            <ul>
                <li><a class="hidden-xs" href="/blog/">主页</a></li>
                <li><a href="/blog/series/">专题</a></li>
                <li><a href="/blog/archives/">归档</a></li>
                <li><a href="/blog/post/link.html">友链</a></li>
                <li><a href="/blog/post/about.html">留言</a></li>
            </ul>
        </nav>
    </div>
    <div id="gkt-cate-nav" class="gkt-header-container hidden-xs">
        
        <nav class="gkt-header-nav float-left">
            <ul>
                
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/go-learn-interface.html">Golang学习</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left active">
                    <a class="float-left" href="/blog/post/go-asm-indroduce.html">Golang汇编</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/tcp-three-way-handshake.html">基础</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/go-how-to-build.html">Golang底层</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/mysql-index-use.html">MySQL</a>
                    
                </li>
                
            </ul>
        </nav>
    </div>
</header>
<div style="height: 44px"></div>
<div class="hidden-xs" style="height: 44px"></div>
<script>
    (function () {
        window.addEventListener('scroll', function () {
            if (window.innerWidth < 768) {
                return;
            }
            var nav = document.querySelector('#gkt-nav');
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            scrollTop > 50 && (nav.classList.add('hide'));
            scrollTop <= 50 && (nav.classList.remove('hide'));
        });
        var cateNavs = document.querySelectorAll('#gkt-cate-nav>nav>ul>li');
        [].slice.call(cateNavs).forEach(function (item) {
            var sub = item.querySelector('.gkt-sub-cate');
            if (!sub) return;
            item.addEventListener('mouseenter', function (e) { sub.style.display = 'block'; }, false);
            item.addEventListener('mouseleave', function (e) { sub.style.display = 'none'; }, false);
        })
    })();
</script>
    <!-- Main Content -->
    <div class="main-container">
        <!-- Main Content -->
<main class="col-xs-12 padding-0 markdown-it">
    <!-- Post Container -->
    
    
    <!-- Post Content -->
<div class="float-left post-container box-shadow">
    <div class="u-arrow-wrapper hidden-xs">
        
        <a class="float-left" href="/blog/post/go-asm-my-asm.html"><i class="u-arrow-left"></i></a>
        
        
        <a class="float-right" href="/blog/post/tcp-three-way-handshake.html"><i class="u-arrow-right"></i></a>
        
    </div>
    <article class="col-xs-12">
        <h1> Golang汇编(四)-汇编眼中的数据结构 </h1>

        

        
        <div class="hidden-lg hidden-md series_links">
            <p> <strong> Golang汇编系列文章链接：</strong></p>
            <ul>
                
                <li>
                    <a href="/blog/post/go-asm-indroduce.html">Golang汇编(一)-Plan9介绍及指令详解</a>
                    <span class="post-item-date">(Feb 6, 2020)</span>
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-method.html">Golang汇编(二)-函数调用</a>
                    <span class="post-item-date">(Feb 16, 2020)</span>
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-my-asm.html">Golang汇编(三)-编写自己的汇编代码</a>
                    <span class="post-item-date">(Feb 19, 2020)</span>
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-datastruct.html">Golang汇编(四)-汇编眼中的数据结构</a>
                    <span class="post-item-date">(Feb 19, 2020)</span>
                </li>
                
            </ul>
        </div>
        
        
        
        <h2 id="标准库中的一些数据结构"><a href="#标准库中的一些数据结构" class="headerlink" title="标准库中的一些数据结构"></a>标准库中的一些数据结构</h2><h2 id="数值类型"><a href="#数值类型" class="headerlink" title="数值类型"></a>数值类型</h2><p>标准库中的数值类型很多:</p>
<ol>
<li>int/int8/int16/int32/int64</li>
<li>uint/uint8/uint16/uint32/uint64</li>
<li>float32/float64</li>
<li>byte/rune</li>
<li>uintptr</li>
</ol>
<p>这些类型在汇编中就是一段存储着数据的连续内存，只是内存长度不一样，操作的时候看好数据长度就行。</p>
<h2 id="array"><a href="#array" class="headerlink" title="array"></a>array</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">	a:= [<span class="number">6</span>]<span class="keyword">int</span>&#123;<span class="number">6</span>, <span class="number">9</span>, <span class="number">1</span>,<span class="number">3</span>,<span class="number">15</span>,<span class="number">26</span>&#125;</span><br><span class="line">	a[<span class="number">1</span>]=<span class="number">4</span></span><br><span class="line"></span><br><span class="line">	b:= [<span class="number">3</span>]<span class="keyword">string</span>&#123;<span class="string">"56"</span>, <span class="string">"678"</span>&#125;</span><br><span class="line">	b[<span class="number">1</span>]=<span class="string">"7"</span></span><br><span class="line">	<span class="built_in">println</span>(a[<span class="number">1</span>],b[<span class="number">1</span>])</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>针对</p>
<p>line4: a:= [6]int{6, 9, 1,3,15,26}<br>line5: a[1]=4</p>
<p>汇编</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">00054 (arr_asm.go:4)	MOVUPS	&quot;&quot;.statictmp_0(SB), X0 &#x2F;&#x2F;将数据拷贝到栈中</span><br><span class="line">00061 (arr_asm.go:4)	MOVUPS	X0, &quot;&quot;.a+24(SP)</span><br><span class="line">00066 (arr_asm.go:4)	MOVUPS	&quot;&quot;.statictmp_0+16(SB), X0</span><br><span class="line">00073 (arr_asm.go:4)	MOVUPS	X0, &quot;&quot;.a+40(SP)</span><br><span class="line">00078 (arr_asm.go:4)	MOVUPS	&quot;&quot;.statictmp_0+32(SB), X0</span><br><span class="line">00085 (arr_asm.go:4)	MOVUPS	X0, &quot;&quot;.a+56(SP)</span><br><span class="line">00090 (arr_asm.go:5)	MOVQ	$4, &quot;&quot;.a+32(SP)   &#x2F;&#x2F;对索引1赋值4</span><br></pre></td></tr></table></figure>

<p>从上面可以看出，数组在汇编中其实就是一段连续的内存，从24(SP) -&gt; 64(SP)一共48个字节，刚好就是6个int类型占用的空间（64位系统）</p>
<p>另外，””.statictmp_0+32(SB)是编译器事先分配到只读数据段(<strong>SRODATA</strong>)的数据，汇编中可以查到</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&quot;&quot;.statictmp_0 SRODATA size&#x3D;48</span><br><span class="line">	0x0000 06 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00</span><br><span class="line">	0x0010 01 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 </span><br><span class="line">	0x0020 0f 00 00 00 00 00 00 00 1a 00 00 00 00 00 00 00  ................</span><br></pre></td></tr></table></figure>



<h2 id="string"><a href="#string" class="headerlink" title="string"></a>string</h2><p>针对上面的代码</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">line7: b:= [<span class="number">3</span>]<span class="keyword">string</span>&#123;<span class="string">"56"</span>, <span class="string">"678"</span>&#125;</span><br><span class="line">line8: b[<span class="number">1</span>]=<span class="string">"7"</span></span><br></pre></td></tr></table></figure>

<p>得到汇编</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">00088 (arr_asm.go:7) XORPS	X0, X0 			&#x2F;&#x2F;初始化内存空间</span><br><span class="line">00091 (arr_asm.go:7) MOVUPS	X0, &quot;&quot;.b+88(SP)</span><br><span class="line">00096 (arr_asm.go:7) XORPS	X0, X0</span><br><span class="line">00099 (arr_asm.go:7) MOVUPS	X0, &quot;&quot;.b+104(SP)</span><br><span class="line">                     </span><br><span class="line">00104 (arr_asm.go:7) LEAQ	go.string.&quot;56&quot;(SB), AX  &#x2F;&#x2F;将字符串地址赋值AX</span><br><span class="line">00111 (arr_asm.go:7) MOVQ	AX, &quot;&quot;.b+88(SP)  &#x2F;&#x2F;复制到数组</span><br><span class="line">00116 (arr_asm.go:7) MOVQ	$2, &quot;&quot;.b+96(SP)  &#x2F;&#x2F;长度为2</span><br><span class="line">                     </span><br><span class="line">00125 (arr_asm.go:7) LEAQ	go.string.&quot;678&quot;(SB), AX</span><br><span class="line">00132 (arr_asm.go:7) MOVQ	AX, &quot;&quot;.b+104(SP)</span><br><span class="line">00137 (arr_asm.go:7) MOVQ	$3, &quot;&quot;.b+112(SP)  &#x2F;&#x2F;长度为3</span><br><span class="line">                     </span><br><span class="line">00146 (arr_asm.go:8) LEAQ	go.string.&quot;7&quot;(SB), AX	</span><br><span class="line">00153 (arr_asm.go:8) MOVQ	AX, &quot;&quot;.b+104(SP)</span><br><span class="line">00158 (arr_asm.go:8) MOVQ	$1, &quot;&quot;.b+112(SP)  &#x2F;&#x2F;长度为1</span><br></pre></td></tr></table></figure>

<p>可以看到在汇编层面 string 就是地址 + 字符串长度。</p>
<h2 id="slice"><a href="#slice" class="headerlink" title="slice"></a>slice</h2><p>在go里面的定义</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Go\src\runtime\slice.go</span></span><br><span class="line"><span class="keyword">type</span> slice <span class="keyword">struct</span> &#123;</span><br><span class="line">	array unsafe.Pointer</span><br><span class="line">	<span class="built_in">len</span>   <span class="keyword">int</span></span><br><span class="line">	<span class="built_in">cap</span>   <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>因此slice在内存中会展开成三个参数:</p>
<ol>
<li>首元素地址</li>
<li>slice 的 len</li>
<li>slice 的 cap</li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">line4: a:=<span class="built_in">make</span>([]<span class="keyword">int</span>,<span class="number">2</span>,<span class="number">4</span>)</span><br><span class="line">line5: a[<span class="number">0</span>]=<span class="number">7</span></span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">00040 (slice_asm.go:4)	XORPS	X0, X0              &#x2F;&#x2F;清空内存空间</span><br><span class="line">00043 (slice_asm.go:4)	MOVUPS	X0, &quot;&quot;..autotmp_1+16(SP)</span><br><span class="line">00048 (slice_asm.go:4)	XORPS	X0, X0</span><br><span class="line">00051 (slice_asm.go:4)	MOVUPS	X0, &quot;&quot;..autotmp_1+32(SP)</span><br><span class="line"></span><br><span class="line">00056 (slice_asm.go:4)	LEAQ	&quot;&quot;..autotmp_1+16(SP), AX &#x2F;&#x2F;获取首元素地址</span><br><span class="line">00061 (slice_asm.go:4)	TESTB	AL, (AX)</span><br><span class="line">00067 (slice_asm.go:4)	MOVQ	AX, &quot;&quot;.a+48(SP) </span><br><span class="line">00072 (slice_asm.go:4)	MOVQ	$2, &quot;&quot;.a+56(SP) &#x2F;&#x2F;len</span><br><span class="line">00081 (slice_asm.go:4)	MOVQ	$4, &quot;&quot;.a+64(SP) &#x2F;&#x2F;cap</span><br><span class="line">00092 (slice_asm.go:5)	MOVQ	$7, &quot;&quot;..autotmp_1+16(SP) &#x2F;&#x2F;赋值</span><br></pre></td></tr></table></figure>



<h3 id="slice-append"><a href="#slice-append" class="headerlink" title="slice.append"></a>slice.append</h3><p>代码</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">line13:    s2 := <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="number">10</span>)</span><br><span class="line">line14:    s2=<span class="built_in">append</span>(s2, <span class="number">9999</span>)</span><br><span class="line">line15:    s2=<span class="built_in">append</span>(s2, <span class="number">8888</span>)</span><br></pre></td></tr></table></figure>

<p>汇编代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">00157 (append.go:13) LEAQ	&quot;&quot;..autotmp_5+80(SP), DI</span><br><span class="line">00162 (append.go:13) XORPS	X0, X0</span><br><span class="line">00165 (append.go:13) LEAQ	-48(DI), DI</span><br><span class="line">00169 (append.go:13) DUFFZERO	$277</span><br><span class="line">00188 (append.go:13) LEAQ	&quot;&quot;..autotmp_5+80(SP), AX &#x2F;&#x2F;清空内存空间</span><br><span class="line">00193 (append.go:13) TESTB	AL, (AX)</span><br><span class="line">00197 (append.go:13) MOVQ	AX, &quot;&quot;.s2+248(SP)      &#x2F;&#x2F;首元素地址ptr</span><br><span class="line">00205 (append.go:13) MOVQ	$10, &quot;&quot;.s2+256(SP)      &#x2F;&#x2F;len</span><br><span class="line">00217 (append.go:13) MOVQ	$10, &quot;&quot;.s2+264(SP)      &#x2F;&#x2F;cap</span><br><span class="line"></span><br><span class="line">00231 (append.go:14) LEAQ	type.int(SB), CX</span><br><span class="line">00238 (append.go:14) MOVQ	CX, (SP)    &#x2F;&#x2F;准备growslice的参数*_type</span><br><span class="line">00242 (append.go:14) MOVQ	AX, 8(SP)    &#x2F;&#x2F;oldslice.ptr</span><br><span class="line">00247 (append.go:14) MOVQ	$10, 16(SP)   &#x2F;&#x2F;oldslice.len</span><br><span class="line">00256 (append.go:14) MOVQ	$10, 24(SP)   &#x2F;&#x2F;oldslice.cap</span><br><span class="line">00265 (append.go:14) MOVQ	$11, 32(SP) &#x2F;&#x2F;new cap</span><br><span class="line">00274 (append.go:14) CALL	runtime.growslice(SB)</span><br><span class="line">00279 (append.go:14) MOVQ	40(SP), AX</span><br><span class="line">00284 (append.go:14) MOVQ	48(SP), CX</span><br><span class="line">00289 (append.go:14) MOVQ	56(SP), DX</span><br><span class="line">00294 (append.go:14) LEAQ	1(CX), BX  &#x2F;&#x2F;记录新len</span><br><span class="line">00300 (append.go:14) MOVQ	$9999, 80(AX) &#x2F;&#x2F;原来数组len为10，在尾部添加就是偏移8*10&#x3D;80字节</span><br><span class="line">                     </span><br><span class="line">00308 (append.go:14) MOVQ	AX, &quot;&quot;.s2+248(SP)</span><br><span class="line">00316 (append.go:14) MOVQ	BX, &quot;&quot;.s2+256(SP)</span><br><span class="line">00324 (append.go:14) MOVQ	DX, &quot;&quot;.s2+264(SP)</span><br><span class="line">00332 (append.go:15) LEAQ	2(CX), SI </span><br><span class="line">00336 (append.go:15) CMPQ	SI, DX </span><br><span class="line">00339 (append.go:15) JLE	348 &#x2F;&#x2F;如果len+2小于cap，直接添加</span><br><span class="line">00341 (append.go:15) JMP	535 &#x2F;&#x2F;否则跳转到扩容代码</span><br><span class="line"></span><br><span class="line">00348 (append.go:15) MOVQ	$8888, 8(AX)(CX*8)</span><br><span class="line">00357 (append.go:15) MOVQ	AX, &quot;&quot;.s2+248(SP)</span><br><span class="line">00365 (append.go:15) MOVQ	SI, &quot;&quot;.s2+256(SP)</span><br><span class="line">00373 (append.go:15) MOVQ	DX, &quot;&quot;.s2+264(SP)</span><br><span class="line">...扩容数组代码             </span><br><span class="line">00535 (append.go:14) MOVQ	CX, &quot;&quot;..autotmp_6+64(SP)</span><br><span class="line">00540 (append.go:15) LEAQ	type.int(SB), CX    </span><br><span class="line">00547 (append.go:15) MOVQ	CX, (SP)   &#x2F;&#x2F;_type</span><br><span class="line">00551 (append.go:15) MOVQ	AX, 8(SP)   &#x2F;&#x2F;oldslice.ptr</span><br><span class="line">00556 (append.go:15) MOVQ	BX, 16(SP)   &#x2F;&#x2F;oldslice.len</span><br><span class="line">00561 (append.go:15) MOVQ	DX, 24(SP)   &#x2F;&#x2F;oldslice.cap</span><br><span class="line">00566 (append.go:15) MOVQ	SI, 32(SP)	&#x2F;&#x2F;new cap</span><br><span class="line">00571 (append.go:15) CALL	runtime.growslice(SB)</span><br><span class="line">00576 (append.go:15) MOVQ	40(SP), AX 	&#x2F;&#x2F;</span><br><span class="line">00581 (append.go:15) MOVQ	48(SP), CX	&#x2F;&#x2F;</span><br><span class="line">00586 (append.go:15) MOVQ	56(SP), DX	&#x2F;&#x2F;</span><br><span class="line">00591 (append.go:15) LEAQ	1(CX), SI	&#x2F;&#x2F;记录新len</span><br><span class="line">00595 (append.go:15) MOVQ	&quot;&quot;..autotmp_6+64(SP), CX	&#x2F;&#x2F;还原cx</span><br><span class="line">00600 (append.go:15) JMP	348   &#x2F;&#x2F;返回继续append</span><br></pre></td></tr></table></figure>

<p>可以看到append代码实际上就是比较len和cap，发现超过cap就会调用growslice进行扩容</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">growslice</span><span class="params">(et *_type, old slice, <span class="built_in">cap</span> <span class="keyword">int</span>)</span> <span class="title">slice</span></span></span><br></pre></td></tr></table></figure>



<h3 id="slicecopy"><a href="#slicecopy" class="headerlink" title="slicecopy"></a>slicecopy</h3><p>测试代码</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">line12:    s1 := <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="number">10</span>)</span><br><span class="line">line13:    s2 := <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="number">10</span>)</span><br><span class="line">line14:    <span class="built_in">copy</span>(s1,s2)</span><br></pre></td></tr></table></figure>

<p>对应汇编</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">00229 (append.go:14)	MOVQ	&quot;&quot;.s1+248(SP), AX</span><br><span class="line">00237 (append.go:14)	MOVQ	&quot;&quot;.s1+240(SP), CX</span><br><span class="line">00245 (append.go:14)	MOVQ	&quot;&quot;.s1+256(SP), DX</span><br><span class="line">00253 (append.go:14)	MOVQ	CX, &quot;&quot;..autotmp_6+288(SP) &#x2F;&#x2F;s1.ptr</span><br><span class="line">00261 (append.go:14)	MOVQ	AX, &quot;&quot;..autotmp_6+296(SP) &#x2F;&#x2F;s1.len</span><br><span class="line">00269 (append.go:14)	MOVQ	DX, &quot;&quot;..autotmp_6+304(SP) &#x2F;&#x2F;s1.cap</span><br><span class="line"></span><br><span class="line">00277 (append.go:14)	MOVQ	&quot;&quot;.s2+216(SP), AX</span><br><span class="line">00285 (append.go:14)	MOVQ	&quot;&quot;.s2+224(SP), CX</span><br><span class="line">00293 (append.go:14)	MOVQ	&quot;&quot;.s2+232(SP), DX</span><br><span class="line">00301 (append.go:14)	MOVQ	AX, &quot;&quot;..autotmp_7+264(SP)  &#x2F;&#x2F;s2.ptr</span><br><span class="line">00309 (append.go:14)	MOVQ	CX, &quot;&quot;..autotmp_7+272(SP)  &#x2F;&#x2F;s2.len</span><br><span class="line">00317 (append.go:14)	MOVQ	DX, &quot;&quot;..autotmp_7+280(SP)	&#x2F;&#x2F;s2.cap</span><br><span class="line"></span><br><span class="line">00325 (append.go:14)	MOVQ	&quot;&quot;..autotmp_6+296(SP), AX</span><br><span class="line">00333 (append.go:14)	MOVQ	AX, &quot;&quot;..autotmp_8+32(SP)</span><br><span class="line">00338 (append.go:14)	MOVQ	&quot;&quot;..autotmp_7+272(SP), CX</span><br><span class="line">00346 (append.go:14)	CMPQ	AX, CX   &#x2F;&#x2F;比较s1，s2的len</span><br><span class="line">00349 (append.go:14)	JGT	356  		&#x2F;&#x2F;s1.len&gt;s2.len</span><br><span class="line">00351 (append.go:14)	JMP	371</span><br><span class="line">00356 (append.go:14)	MOVQ	&quot;&quot;..autotmp_7+272(SP), AX</span><br><span class="line">00364 (append.go:14)	MOVQ	AX, &quot;&quot;..autotmp_8+32(SP)</span><br><span class="line">00369 (append.go:14)	JMP	371</span><br><span class="line">00371 (append.go:14)	MOVQ	&quot;&quot;..autotmp_7+264(SP), AX</span><br><span class="line">00379 (append.go:14)	CMPQ	&quot;&quot;..autotmp_6+288(SP), AX</span><br><span class="line">00387 (append.go:14)	JNE	394  &#x2F;&#x2F;s1.ptr !&#x3D; s2.ptr 调用memmove</span><br><span class="line">00389 (append.go:14)	JMP	450  &#x2F;&#x2F; s1.ptr &#x3D;&#x3D; s2.ptr 指向同一个数组，不用拷贝</span><br><span class="line">00394 (append.go:14)	MOVQ	&quot;&quot;..autotmp_8+32(SP), AX</span><br><span class="line">00399 (append.go:14)	MOVQ	AX, &quot;&quot;..autotmp_9+24(SP) &#x2F;&#x2F;获取更小的size</span><br><span class="line"></span><br><span class="line">00404 (append.go:14)	MOVQ	&quot;&quot;..autotmp_6+288(SP), AX &#x2F;&#x2F;to.array</span><br><span class="line">00412 (append.go:14)	MOVQ	AX, (SP)</span><br><span class="line"></span><br><span class="line">00416 (append.go:14)	MOVQ	&quot;&quot;..autotmp_7+264(SP), AX</span><br><span class="line">00424 (append.go:14)	MOVQ	AX, 8(SP)     &#x2F;&#x2F;from.array</span><br><span class="line"></span><br><span class="line">00429 (append.go:14)	MOVQ	&quot;&quot;..autotmp_9+24(SP), AX  &#x2F;&#x2F;更小的size</span><br><span class="line">00434 (append.go:14)	SHLQ	$3, AX &#x2F;&#x2F;左移3位相当于*8，长度转字节数</span><br><span class="line">00438 (append.go:14)	MOVQ	AX, 16(SP)</span><br><span class="line">00443 (append.go:14)	CALL	runtime.memmove(SB)</span><br></pre></td></tr></table></figure>

<p>可以看出copy函数先比较s1,s2对应的底层数组，如果是指向同一个数组就直接返回，如果不是则比较s1，s2的len，取更小的那个，然后调用runtime.memmove</p>
<p>对应的源码是Go\src\runtime\slice.go</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">slicecopy</span><span class="params">(to, fm slice, width <span class="keyword">uintptr</span>)</span> <span class="title">int</span></span> &#123;</span><br><span class="line">	<span class="keyword">if</span> fm.<span class="built_in">len</span> == <span class="number">0</span> || to.<span class="built_in">len</span> == <span class="number">0</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	n := fm.<span class="built_in">len</span></span><br><span class="line">	<span class="keyword">if</span> to.<span class="built_in">len</span> &lt; n &#123;</span><br><span class="line">		n = to.<span class="built_in">len</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> width == <span class="number">0</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> n</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	size := <span class="keyword">uintptr</span>(n) * width</span><br><span class="line">	<span class="keyword">if</span> size == <span class="number">1</span> &#123; <span class="comment">// common case worth about 2x to do here</span></span><br><span class="line">		<span class="comment">// <span class="doctag">TODO:</span> is this still worth it with new memmove impl?</span></span><br><span class="line">		*(*<span class="keyword">byte</span>)(to.array) = *(*<span class="keyword">byte</span>)(fm.array) <span class="comment">// known to be a byte pointer</span></span><br><span class="line">	&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">		memmove(to.array, fm.array, size)</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> n</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="struct"><a href="#struct" class="headerlink" title="struct"></a>struct</h2><p>struct 在汇编层面实际上就是一段连续内存，在作为参数传给函数时，会将其展开在 caller 的栈上传给对应的 callee:</p>
<p>struct.go</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> address <span class="keyword">struct</span> &#123;</span><br><span class="line">    lng <span class="keyword">int</span></span><br><span class="line">    lat <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> person <span class="keyword">struct</span> &#123;</span><br><span class="line">    age    <span class="keyword">int</span></span><br><span class="line">    height <span class="keyword">int</span></span><br><span class="line">    addr   address</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">readStruct</span><span class="params">(p person)</span> <span class="params">(<span class="keyword">int</span>, <span class="keyword">int</span>, <span class="keyword">int</span>, <span class="keyword">int</span>)</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> p = person&#123;</span><br><span class="line">        age:    <span class="number">99</span>,</span><br><span class="line">        height: <span class="number">88</span>,</span><br><span class="line">        addr: address&#123;</span><br><span class="line">            lng: <span class="number">77</span>,</span><br><span class="line">            lat: <span class="number">66</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">    a, b, c, d := readStruct(p)</span><br><span class="line">    <span class="built_in">println</span>(a, b, c, d)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>struct会展开按声明顺序，地址从小到大分布在内存中，一次在栈中的布局是</p>
<p><img src="http://river.marvelthanos.com/blog/20200312/qimbU8YafFlC.png?imageslim" alt="mark"></p>
<p>因此可以编写汇编输出结果，struct.s</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#include &quot;textflag.h&quot;</span><br><span class="line"></span><br><span class="line">TEXT ·readStruct(SB), NOSPLIT, $0-64</span><br><span class="line">    MOVQ arg0+0(FP), AX</span><br><span class="line">    MOVQ AX, ret0+32(FP)</span><br><span class="line">    MOVQ arg1+8(FP), AX</span><br><span class="line">    MOVQ AX, ret1+40(FP)</span><br><span class="line">    MOVQ arg2+16(FP), AX</span><br><span class="line">    MOVQ AX, ret2+48(FP)</span><br><span class="line">    MOVQ arg3+24(FP), AX</span><br><span class="line">    MOVQ AX, ret3+56(FP)</span><br><span class="line">    RET</span><br></pre></td></tr></table></figure>

<p>上述的程序会输出 99, 88, 77, 66，这表明即使是内嵌结构体，在内存分布上依然是连续的。</p>
<h2 id="map"><a href="#map" class="headerlink" title="map"></a>map</h2><p>通过对下述文件进行汇编(go tool compile -S)，我们可以得到一个 map 在对某个 key 赋值时所需要做的操作:</p>
<p>m.go:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> m = <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">int</span>&#123;&#125;</span><br><span class="line">    m[<span class="number">43</span>] = <span class="number">1</span></span><br><span class="line">    <span class="keyword">var</span> n = <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>&#123;&#125;</span><br><span class="line">    n[<span class="string">"abc"</span>] = <span class="number">1</span></span><br><span class="line">    <span class="built_in">println</span>(m, n)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>看一看第5行：<code>m[43]=1</code></p>
<p>对于不同类型的 map，对其赋值需要执行的 runtime 中的 assign 函数是不同的，从汇编结果看出map[int]int调用的是<code>mapassign_fast64</code></p>
<p>函数定义</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Go\src\runtime\map_fast64</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">mapassign_fast64</span><span class="params">(t *maptype, h *hmap, key <span class="keyword">uint64</span>)</span> <span class="title">unsafe</span>.<span class="title">Pointer</span></span></span><br></pre></td></tr></table></figure>

<p>对应汇编:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">00197 (map_asm.go:5)	LEAQ	type.map[int]int(SB), AX</span><br><span class="line">00204 (map_asm.go:5)	MOVQ	AX, (SP)   &#x2F;&#x2F;设置参数1 *maptype</span><br><span class="line"></span><br><span class="line">00208 (map_asm.go:5)	MOVQ	&quot;&quot;.m+192(SP), AX</span><br><span class="line">00216 (map_asm.go:5)	MOVQ	AX, 8(SP)  &#x2F;&#x2F;设置参数2 *hmap</span><br><span class="line">00221 (map_asm.go:5)	MOVQ	$43, 16(SP) &#x2F;&#x2F;设置参数3 key</span><br><span class="line">00230 (map_asm.go:5)	CALL	runtime.mapassign_fast64(SB) &#x2F;&#x2F;调用函数</span><br><span class="line">00235 (map_asm.go:5)	MOVQ	24(SP), AX &#x2F;&#x2F; 返回值</span><br><span class="line">00250 (map_asm.go:5)	MOVQ	$1, (AX)   &#x2F;&#x2F;赋值为1</span><br></pre></td></tr></table></figure>

<p>从中我们可以看出，返回参数就是 key 对应的可以写值的内存地址，拿到该地址后我们把想要写的值写进去就可以了:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">MOVQ    24(SP), AX</span><br><span class="line">MOVQ    $1, (AX)</span><br></pre></td></tr></table></figure>



<p>参考文档：</p>
<p><a href="http://blog.rootk.com/post/golang-asm-example.html" target="_blank" rel="noopener">Golang内置函数和过程调用汇编代码分析</a></p>

        
<script src="/blog/js/qrious.min.js"></script>


        <hr>
        <div>
            
            <p>
                <span>专题: </span>
                
                <a href="/blog/series/#Golang汇编">
                    <code key="Golang汇编" class="post-label">Golang汇编</code>
                </a>
                
            </p>
            
            <p>
                <span>本文发表于 2020-02-19，最后修改于 2020-03-15。</span>
            </p>
            <!-- 文章末尾的提示 start -->
            
            
            
                
            <!-- 文章末尾的提示 end -->
        </div>
        <hr />
        <p name="pagination" style="font-size: 1.2em">
    
    <a class="float-left" href="/blog/post/go-asm-my-asm.html">上一篇 « Golang汇编(三)-编写自己的汇编代码</a>
    
    
    <a class="float-right" href="/blog/post/tcp-three-way-handshake.html">下一篇 » 简述TCP“3次握手，4次挥手”</a>
    
</p>
    </article>
    <!-- 赞赏 -->
    <!--打赏-->

    <!-- 推荐阅读三篇文章 -->
    <div class="col-xs-12">
        <h3>推荐阅读</h3>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/go.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang"
                    title="Golang">Golang</a>
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang源码"
                    title="Golang源码">Golang源码</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/go-learn-lib-sorts.html" class="title">
                Go源码学习 sort包
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-03-11，</span>
                    <span class="hidden-xs">全文8862字，</span>
                    <span>阅读约30分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/database/database.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#MySQL"
                    title="MySQL">MySQL</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/mysql-index-base.html" class="title">
                《高性能MySQL》笔记-索引基础
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-03-02，</span>
                    <span class="hidden-xs">全文9540字，</span>
                    <span>阅读约32分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/database/database.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#MySQL"
                    title="MySQL">MySQL</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/mysql-index-use.html" class="title">
                《高性能MySQL》笔记-索引优化
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-03-01，</span>
                    <span class="hidden-xs">全文13286字，</span>
                    <span>阅读约45分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
    </div>
    <div class="col-xs-12">
        <!-- 标签列表 -->
        <!-- Featured Tags -->
<style>
    #featured-tag .post-tag-item {
        font-size: 12px;
        line-height: 30px;
        display: inline-block;
        height: 30px;
        margin: 5px 0px;
        padding: 0 7px;
        color: #333;
        border-radius: 15px;
        background: #f6f6f6;
    }

    #featured-tag .post-tag-item:hover {
        color: #337ab7;
    }
</style>
<div id="featured-tag">
    
    <a class="post-tag-item" href="/blog/tags/#关于我" title="关于我"
        rel="1">#关于我 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#友链" title="友链"
        rel="1">#友链 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang汇编" title="Golang汇编"
        rel="4">#Golang汇编 (4) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang底层" title="Golang底层"
        rel="5">#Golang底层 (5) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang" title="Golang"
        rel="8">#Golang (8) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang基础" title="Golang基础"
        rel="1">#Golang基础 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang源码" title="Golang源码"
        rel="2">#Golang源码 (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#基础" title="基础"
        rel="2">#基础 (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#tcp/http" title="tcp/http"
        rel="2">#tcp/http (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#MySQL" title="MySQL"
        rel="3">#MySQL (3) </a>
    
    <a class="post-tag-item" href="/blog/tags/#MySQL优化" title="MySQL优化"
        rel="1">#MySQL优化 (1) </a>
    
</div>
    </div>
    <!-- 评论 -->
    <div class="col-xs-12">
        
    </div>
</div>
<aside class="float-left gkt-sidebar hidden-xs hidden-sm">
    <div style="clear: both"></div>
    <div class="gkt-sidebar-wrapper">
        <section class="box-shadow"><style>
    .gkt-summary {
        border: 1px solid #DDDDDD;
        border-radius: 3px;
        padding: 5px;
        width: 100%;
    }


    .gkt-summary nav {
        overflow: hidden;
    }

    .gkt-summary nav a {
        display: inline-block;
        text-align: center;
        color: #333;
        font-size: 12px;
    }

    .gkt-summary nav span {
        display: block;
    }

    .gkt-summary nav .middle {
        border-left: 1px solid #eaecef;
        border-right: 1px solid #eaecef;
    }

    .gkt-summary .number {
        font-weight: bold;
    }

    .gkt-summary .link-list {
        margin-top: 5px;
        margin-bottom: -5px;
        padding-top: 7px;
        border-top: 1px dashed #999;
        display: flex;
    }

    .gkt-summary .link-list a {
        flex: 1;
    }

    .gkt-summary .link-list img {
        width: 25px;
        height: 25px;
    }
</style>

<div class="gkt-summary">
    <nav>
        <a href="/blog/" class="col-xs-4">
            <number class="number">15</number><span>文章</span>
        </a>
        <a href="/blog/series" class="col-xs-4 middle">
            <number class="number">5</number><span>专题</span>
        </a>
        <a href="/blog/tags" class="col-xs-4">
            <number class="number">11</number><span>标签</span>
        </a>
    </nav>

    
    <div class="link-list">
        
        <a href="https://marvelthanos.com" target="_blank" rel="noopener"><img src="/blog/img/related_links/thanos.webp" /></a>
        
    </div>
    
</div></section>
        
        
        <section class="gkt-sidebar-content box-shadow">
            <strong>Golang汇编</strong>
            <ul>
                
                <li>
                    <a href="/blog/post/go-asm-indroduce.html"
                        class="">Golang汇编(一)-Plan9介绍及指令详解</a>
                    
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-method.html"
                        class="">Golang汇编(二)-函数调用</a>
                    
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-my-asm.html"
                        class="">Golang汇编(三)-编写自己的汇编代码</a>
                    
                </li>
                
                <li>
                    <a href="/blog/post/go-asm-datastruct.html"
                        class="gkt-sidebar-active">Golang汇编(四)-汇编眼中的数据结构</a>
                    
                    <!-- Table of Contents -->
<div id="sidebar-toc">
  <!-- TOC  -->
  
  <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#标准库中的一些数据结构"><span class="toc-nav-text">标准库中的一些数据结构</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#数值类型"><span class="toc-nav-text">数值类型</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#array"><span class="toc-nav-text">array</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#string"><span class="toc-nav-text">string</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#slice"><span class="toc-nav-text">slice</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#struct"><span class="toc-nav-text">struct</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#map"><span class="toc-nav-text">map</span></a></li></ol>
  
</div>

<script>
  (function () {
    var h2 = document.querySelectorAll('article h2');
    var h3 = document.querySelectorAll('article h3');
    var linkList = document.querySelectorAll('#sidebar-toc a');

    function findLinkElement(name) {
      for (var i = 0; i < linkList.length; i++) {
        var items = linkList[i].href.split('#');
        if (items && items[items.length - 1] === encodeURIComponent(name)) {
          return i;
        }
      }
      return -1;
    }

    function activeLink(titleList) {
      var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      for (var i = titleList.length - 1; i >= 0; i--) {
        if (scrollTop - titleList[i].offsetTop > 0) {
          var index = findLinkElement(titleList[i].id);
          index != -1 && linkList[index].classList.add('gkt-sidebar-active');
          break;
        }
      }
    }

    window.addEventListener("scroll", function (e) {
      [].slice.call(linkList).forEach(function (link) {
        link.classList.remove('gkt-sidebar-active');
      })
      activeLink(h2);
    })
  })();
</script>
                    
                </li>
                
            </ul>
        </section>
        
        
        <section class="box-shadow">
            <strong>最近的文章</strong>
            <ul>
                
                <li>
                    <a href="/blog/post/go-learn-lib-sorts.html">Go源码学习 sort包</a>
                </li>
                
                <li>
                    <a href="/blog/post/mysql-optimize-explain.html">EXPLAIN-执行计划查询命令</a>
                </li>
                
                <li>
                    <a href="/blog/post/mysql-index-base.html">《高性能MySQL》笔记-索引基础</a>
                </li>
                
            </ul>
        </section>
        <section class="box-shadow text-center">
            
        </section>
    </div>
</aside>

<script>
    (function () {
        var ele = getDom('.gkt-sidebar-content')
        var wrapper = getDom('.gkt-sidebar-wrapper')
        var last = 0
        window.addEventListener("scroll", function (e) {
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            var isDown = scrollTop > last;
            var pos = getPosition(ele).y - scrollTop;
            var downLimit = 50;
            var upLimit = -100;
            // uarrow.style.marginTop = scrollTop + 'px';
            isDown && pos <= downLimit && wrapper.classList.add("gkt-sidebar-fixed");
            !isDown && pos > upLimit && wrapper.classList.remove("gkt-sidebar-fixed");
            last = scrollTop
        })
    })();
    (function () {
        function resizeUArrow() {
            var s = getDom('.u-arrow-wrapper').style
            var pc = getDom('.post-container')
            s.left = getPosition(pc).x + 'px';
            s.width = pc.clientWidth + 'px';
        }
        resizeUArrow()
        window.addEventListener('resize', resizeUArrow);
    })();
</script>

    
</main>
    </div>
    <style>
    img#go-top {
        position: fixed;
        bottom: 100px;
        width: 50px;
        cursor: pointer;
        z-index: 9999;
    }
</style>
<img id="go-top" src="/blog/icon/top.png" class="hidden-xs" style="display: none" />
<script>
    (function () {
        var goTop = document.getElementById('go-top');
        var mainContainer = document.querySelector('.main-container');
        
        goTop.addEventListener('click', function () {
            window.scroll(0, 0);
        }, false);
        window.addEventListener('scroll', function () {
            var right = document.body.offsetWidth - mainContainer.getBoundingClientRect().right;
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            goTop.style.right = right + 10 + 'px'
            scrollTop > 700 && (goTop.style.display = "block");
            scrollTop <= 700 && (goTop.style.display = "none");
        });
    })();
</script>
    <style>
    #geektutu-click-img-container {
        position: fixed;
        left: 0;
        top: 0;
        text-align: center;
        width: 100%;
        display: none;
        z-index: 9999;
    }

    #geektutu-click-img-container img {
        object-fit: contain;
        background: #eaecef;
        padding: 15px;
        border-radius: 10px;
        height: auto;
        width: auto;
        vertical-align: middle;
    }
</style>


<div id="geektutu-click-img-container">
    <img src="" alt="Big Image">
</div>

<script>
    (function () {
        var container = document.querySelector('#geektutu-click-img-container')
        var targetImg = container.querySelector('img')
        var imgs = document.querySelectorAll('article img');
        targetImg.addEventListener('click', function (e) {
            container.style.display = 'none';
            e && e.stopPropagation && e.stopPropagation();
        }, false);

        for (var i = 0; i < imgs.length; ++i) {
            var img = imgs[i];
            img.addEventListener('click', (function (src, rate) {
                return function (e) {
                    e && e.stopPropagation && e.stopPropagation();
                    if (window.innerWidth < 980) {
                        return
                    }
                    targetImg.style.height = targetImg.style.width = 'auto';
                    if (window.innerWidth / window.innerHeight > rate) {
                        targetImg.style.height = (window.innerHeight - 20) + 'px';
                    } else {
                        targetImg.style.width = (window.innerWidth - 20) + 'px';
                    }
                    container.style.height = window.innerHeight + 'px'
                    container.style.lineHeight = window.innerHeight + 'px'
                    container.style.display = 'block';
                    targetImg.src = src;
                };
            }(img.src, img.width / img.height)), false)
        }
    })();
</script>
    <!-- Footer -->
    <!-- Footer -->
<style>
    footer {
        width: 100%;
        line-height: 1.5;
        padding: 20px;
    }

    footer a {
        color: #333;
        text-decoration: none;
    }

    .footer-hexo img {
        height: 20px;
        margin-bottom: -5px;
    }

    .footer-hexo a {
        color: #337ab7;
    }
</style>
<footer class="text-center col-xs-12">
    <p>
        <small>© 2020 - Evrn - </small>
        <small>
            <a target="_blank" rel="nofollow noopener" href="http://www.miitbeian.gov.cn/"></a>
        </small>
    </p>
    <p class="footer-hexo">
        <!-- 但若直接使用或修改主题，请务必保留这段声明 -->
        <small>Powered by <a target="_blank" href="https://hexo.io">Hexo</a> | Theme
            <a target="_blank" href="https://geektutu.com">Geektutu</a>
            <a href="https://github.com/geektutu/hexo-theme-geektutu" target="_blank" rel="noopener">
                <img src=""
                    alt="Github Star">
            </a>
        </small>
    </p>
    
    <p>
        <small>
            <span id="busuanzi_container_site_pv">👁<span id="busuanzi_value_site_pv"></span></span> &nbsp;
            <span id="busuanzi_container_page_pv">📚<span id="busuanzi_value_page_pv"></span></span>
        </small>
    </p>
    
    

</footer>


<script>
    window.addEventListener('load', function () {
        globalAddScript('//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js');
    })
</script>

<!-- Baidu Tongji -->





    <script>
        // 非本站网址，新开tab页签
        (function () {
            var stopBubble = function (e) {
                e && e.stopPropagation && e.stopPropagation();
            }
            var links = document.querySelectorAll('a');
            [].slice.call(links).forEach(function (item) {
                if (item.href && item.href.indexOf(window.location.host) === -1) {
                    item.target = '_blank'
                }
                // 阻止冒泡，不触发彩蛋。
                item.addEventListener('click', stopBubble, false);
            });
            var article = document.querySelector('article');
            article && article.addEventListener('click', stopBubble, false)
        })();
    </script>
    
</body>

</html>